#ifndef SYNTAX_H
#define SYNTAX_H
#include "allerr.h"
#include "token.h"
#include "buffer.h"
#include "scanner.h"
#include "converted.h"
token next_token_buffer=MAXNOFTOKEN;
token next_token()
{
	return (next_token_buffer==MAXNOFTOKEN)?(next_token_buffer=scanner()):next_token_buffer;
}
void match(token matching)
{
	if(next_token_buffer==MAXNOFTOKEN)
		next_token_buffer=scanner();
	if(matching!=next_token_buffer)
		post_error(syntax,next_token_buffer,matching);
	next_token_buffer=MAXNOFTOKEN;
}
void synClear()
{
	match(CLEAR);
	match(VALUE);
	int p=lookup(buffer);
	if(p==0)p=enter(buffer);
	addCode(CLEAR,p);
	match(SEMICOLON);
}
string intMaxStr="2147483647";
int GetNumber()
{
	if(strlen(buffer)>10)
	{
		post_error(range,strlen(buffer),0);
		return 0;
	}
	if(strlen(buffer)==10)
	{
		int bigger=0;
		for(int i=0;i<10;i++)
		{
			if(buffer[i]<intMaxStr[i])break;
			if(buffer[i]>intMaxStr[i])
			{
				bigger=1;
				break;
			}
		}
		if(bigger==1)
		{
			post_error(range,2147483647,0);
			return 0;
		}
	}
	int x=0;
	for(int i=0;isdigit(buffer[i]);i++)
		x=(x<<3)+(x<<1)+buffer[i]-48;
	return x;
}
void synIncr()
{
	match(INCR);
	match(VALUE);
	int p=lookup(buffer);
	if(p==0)p=enter(buffer);
	addCode(INCR,p);
	match(SEMICOLON);
}
void synDecr()
{
	match(DECR);
	match(VALUE);
	int p=lookup(buffer);
	if(p==0)p=enter(buffer);
	addCode(DECR,p);
	match(SEMICOLON);
}
void synWhile()
{
	int temp1,temp2,temp3,temp4;
	match(WHILE);
	switch(next_token())
	{
		case DIGIT:
			temp1=DIGIT;
			temp2=GetNumber();
			match(DIGIT);
			break;
		case VALUE:
			temp1=VALUE;
			temp2=lookup(buffer);
			if(temp2==0)
			{
				post_error(syntax,VALUE,0);
				exit(0);
			}
			match(VALUE);
			break;
	}
	match(NOT);
	switch(next_token())
	{
		case DIGIT:
			temp3=DIGIT;
			temp4=GetNumber();
			match(DIGIT);
			break;
		case VALUE:
			temp3=VALUE;
			temp4=lookup(buffer);
			if(temp4==0)
			{
				post_error(syntax,VALUE,0);
				exit(0);
			}
			match(VALUE);
			break;
	}
	match(COLON);
	int p=addWhile(temp1,temp2,temp3,temp4);
	p=addCode(WHILE,p);
	while(next_token()!=NEXT)
	{
		switch(next_token())
		{
			case CLEAR:
				synClear();
				break;
			case INCR:
				synIncr();
				break;
			case DECR:
				synDecr();
				break;
			case WHILE:
				synWhile();
				break;
			case SEMICOLON:
				match(SEMICOLON);
				break;
			default:
				post_error(syntax,next_token(),-1);
				match(next_token());
		}
	}
	match(NEXT);
	whileValue[code[p].p].nextp=addCode(NEXT,p);
	match(SEMICOLON);
}
void input()
{
	char sbuffer[33];
	printf("INPUT:\n");
	while(1)
	{
		match(VALUE);
		if(strcmp(buffer,"HALT")==0)break;
		strcpy_s(sbuffer, 33, buffer);
		match(COLON);
		match(DIGIT);
		int n=GetNumber();
		int p=lookup(sbuffer);
		if(p==0)p=enter(sbuffer);
		value[p]=n;
		match(SEMICOLON);
	}
	return ;
}
void program()
{
	printf("ProGram:\n");
	while(next_token()!=SCANEOF)
	{
		switch(next_token())
		{
			case CLEAR:
				synClear();
				break;
			case INCR:
				synIncr();
				break;
			case DECR:
				synDecr();
				break;
			case WHILE:
				synWhile();
				break;
			case SEMICOLON:
				match(SEMICOLON);
				break;
			default:
				post_error(syntax,next_token(),-1);
				match(next_token());
		}
	}
	match(SCANEOF);
	addCode(HALT,0);
}
void output()
{
	printf("OUTPUT:\n");
	for(int i=1;i<cntstion;i++)
	{
		printf("%s:%d;\n",tempcnts[i],value[i]);
	}
	return ;
}
#endif
